﻿/*
 * This software is the confidential and proprietary
 * information of NetBay
 * Such confidential information should not be disclosed
 * NetBay copyright(c) 2010
 */

#region Using
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using NetBay.Core.Log;
using System.IO;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Data;
using System.Reflection;
using System.Collections;

#endregion

namespace NetBay.Core.Tools
{
    
    public static class XMLTools
    {
        #region XML
        /// <summary>
        /// Récupère la valeur d'un noeud dans un XML
        /// </summary>
        /// <param name="p_oXmlDocument">Document XML</param>
        /// <param name="p_sAbsoluteXPath">XPath absolu du noeud contenant la valeur</param>
        /// <returns>La valeur</returns>
        public static string GetValueFromXmlDocument(XmlDocument p_oXmlDocument, string p_sAbsoluteXPath)
        {
            string rValue = string.Empty;
            try
            {
                if (p_oXmlDocument.NameTable == null) return null;
                //On crée le namespace manager et on ajoute tous les namespaces contenus dans le xml
                XmlNamespaceManager namespaceManager = new XmlNamespaceManager(p_oXmlDocument.NameTable);
                foreach (XmlAttribute attribute in p_oXmlDocument.DocumentElement.Attributes)
                {
                    if (attribute.Name.Contains("xmlns:"))
                    {
                        string prefix = attribute.Name.Replace("xmlns:", "");
                        namespaceManager.AddNamespace(prefix, attribute.Value);
                    }
                }

                XmlNode node = p_oXmlDocument.SelectSingleNode(p_sAbsoluteXPath, namespaceManager);
                if (node == null)
                {
                    rValue = null;
                }
                else
                {
                    rValue = node.InnerText;
                }
            }
            catch (Exception ex)
            {
                LogManager.Instance().LogErrorFormat(ex, "Error. Details");
            }
            return rValue;
        }


        /// <summary>
        /// Récupère la valeur d'un noeud dans un XML
        /// </summary>
        /// <param name="p_oXmlParentNode">Noeud du XML dans lequel on fait la recherche</param>
        /// <param name="p_sRelativeXPath">XPath relatif du noeud contenant la valeur </param>
        /// <returns>La valeur</returns>
        public static string GetValueFromXmlNode(XmlNode p_oXmlParentNode, string p_sRelativeXPath)
        {
            string rValue = string.Empty;
            try
            {
                //attention pas de / au début
                if (p_sRelativeXPath[0] == '/')
                    p_sRelativeXPath = p_sRelativeXPath.Substring(1);

                XmlDocument xmlDocument = p_oXmlParentNode.OwnerDocument;
                if (xmlDocument == null) return null;

                //On crée le namespace manager et on ajoute tous les namespaces contenus dans le xml
                XmlNamespaceManager namespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
                foreach (XmlAttribute attribute in xmlDocument.DocumentElement.Attributes)
                {
                    if (attribute.Name.Contains("xmlns:"))
                    {
                        string prefix = attribute.Name.Replace("xmlns:", "");
                        namespaceManager.AddNamespace(prefix, attribute.Value);
                    }
                }

                XmlNode node = p_oXmlParentNode.SelectSingleNode(p_sRelativeXPath, namespaceManager);
                if (node == null)
                {
                    rValue = null;
                }
                else
                {
                    rValue = node.InnerText;
                }
            }
            catch (Exception ex)
            {
                LogManager.Instance().LogErrorFormat(ex, "Error. Details");
            }
            return rValue;

        }


        /// <summary>
        /// Récupère la valeur d'un neoud d'un XML
        /// </summary>
        /// <param name="p_oXmlDocument">Document XML</param>
        /// <param name="p_sXPath">Xpath du noeud</param>
        /// <returns>La valeur</returns>
        public static string GetNodeValue(XmlDocument p_oXmlDocument, string p_sXPath)
        {
            string rValue = string.Empty;
            try
            {
                XmlNode xmlNode = p_oXmlDocument.SelectSingleNode(p_sXPath);
                rValue = xmlNode.InnerText;
            }
            catch (Exception ex)
            {
                LogManager.Instance().LogErrorFormat(ex, "Error. Details");
            }
            return rValue;
        }

        /// <summary>
        /// Gets the nodes.
        /// </summary>
        /// <param name="p_sXmlFilePath">The XML file path.</param>
        /// <param name="p_sXPathQuery">The x path query.</param>
        /// <returns></returns>
        public static XmlNodeList GetNodes(string p_sXmlFilePath, string p_sXPathQuery)
        {
            if (!File.Exists(p_sXmlFilePath))
                return null;
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(p_sXmlFilePath);
            XmlNode root = xmlDoc.DocumentElement;
            return root.SelectNodes(p_sXPathQuery);
        }

        public static void AddNodeValues(
            XmlDocument p_oXmlDocument,
            string p_sParentXPath,
            Dictionary<string, string> p_oKeyValuesDict)
        {
            foreach (KeyValuePair<string, string> dictEntry in p_oKeyValuesDict)
            {
                XmlNode xmlNode = p_oXmlDocument.SelectSingleNode(
                    p_sParentXPath + "/" + dictEntry.Key);
                if (xmlNode == null)
                {
                    xmlNode = p_oXmlDocument.CreateElement(dictEntry.Key);
                    XmlNode mainNode = p_oXmlDocument.SelectSingleNode(p_sParentXPath);
                    mainNode.AppendChild(xmlNode);
                }
                xmlNode.InnerText = dictEntry.Value.ToString();
            }
        }

        /// <summary>
        /// Adds the node attributes.
        /// </summary>
        /// <param name="p_oXmlDocument">The XML document.</param>
        /// <param name="p_sParentXPath">The parent X path.</param>
        /// <param name="p_oAttributesDict">The attributes dict.</param>
        public static void AddNodeAttributes(
            XmlDocument p_oXmlDocument,
            string p_sParentXPath,
            Dictionary<string, string> p_oAttributesDict)
        {
            XmlNode xmlNode = p_oXmlDocument.SelectSingleNode(p_sParentXPath);
            foreach (KeyValuePair<string, string> dictEntry in p_oAttributesDict)
            {
                if (xmlNode.Attributes[dictEntry.Key] != null)
                {
                    xmlNode.Attributes[dictEntry.Key].InnerText = dictEntry.Value;
                }
                else
                {
                    XmlAttribute xmlAttribute = p_oXmlDocument.CreateAttribute(dictEntry.Key);
                    xmlAttribute.InnerText = dictEntry.Value;
                    xmlNode.Attributes.Append(xmlAttribute);
                }
            }
        }

        /// <summary>
        /// Adds the node attributes.
        /// </summary>
        /// <param name="p_oXmlDocument">The XML document.</param>
        /// <param name="p_sParentXPath">The parent X path.</param>
        /// <param name="p_sAttributesKey">The attributes key.</param>
        /// <param name="p_sAttributesValue">The attributes value.</param>
        public static void AddNodeAttributes(
            XmlDocument p_oXmlDocument,
            string p_sParentXPath,
            string p_sAttributesKey,
            string p_sAttributesValue)
        {
            Dictionary<string, string> attributes = new Dictionary<string, string>();
            attributes.Add(p_sAttributesKey, p_sAttributesValue);
            AddNodeAttributes(p_oXmlDocument, p_sParentXPath, attributes);
        }

        #endregion
    }

    public class Tools
    {
        /// <summary>
        /// Determines whether [is in design mode].
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if [is in design mode]; otherwise, <c>false</c>.
        /// </returns>
        [Obsolete("Use this.DesignMode directly in the form instead")]
        public static bool IsInDesignMode()
        {
            return System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime;
        }

        /// <summary>
        /// convert a string To a bytes Array
        /// </summary>
        /// <param name="p_sStringToConvert">Strong to convert</param>
        /// <returns>The resulting bytes array</returns>
        public static byte[] ConvertStringToByteArray(string p_sStringToConvert)
        {
            byte[] L_oRByte = null;
            try
            {
                L_oRByte = (new UnicodeEncoding()).GetBytes(p_sStringToConvert);
            }
            catch (Exception ex)
            {
                LogManager.Instance().LogErrorFormat(ex, "Error. Details");
            }
            return L_oRByte;
        }

        /// <summary>
        /// Converts the time specified in Unix Time related to the 01/01/1970
        /// </summary>
        /// <param name="p_dtTime">The time.</param>
        /// <returns></returns>
        public static long ToUnixTime(DateTime p_dtTime)
        {
            return (long)((p_dtTime.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalSeconds);
        }

        /// <summary>
        /// Parses the date time (accepts empty date).
        /// </summary>
        /// <param name="p_sStringDateTime">The string date time.</param>
        /// <param name="p_oProvider">The format provider.</param>
        /// <param name="p_dtDateTime">The date time.</param>
        /// <returns></returns>
        public static bool ParseDateTime(
            string p_sStringDateTime,
            IFormatProvider p_oProvider,
            out DateTime p_dtDateTime)
        {
            return ParseDateTime(
                p_sStringDateTime,
                p_oProvider,
                out p_dtDateTime,
                true);
        }


        /// <summary>
        /// Parses the date time.
        /// </summary>
        /// <param name="p_sStringDateTime">The string date time.</param>
        /// <param name="p_dtDateTime">The date time.</param>
        /// <param name="p_bAcceptEmptyDate">if set to <c>true</c> [accept empty date].</param>
        /// <returns></returns>
        public static bool ParseDateTime(
            string p_sStringDateTime,
            IFormatProvider p_oCultureInfo,
            out DateTime p_dtDateTime,
            bool p_bAcceptEmptyDate)
        {
            p_dtDateTime = DateTime.MinValue;
            DateTime L_dtTmpDateTime;
            if (String.IsNullOrEmpty(p_sStringDateTime) && p_bAcceptEmptyDate)
            {
                return true;
            }
            else if (!DateTime.TryParse(
                                p_sStringDateTime,
                                p_oCultureInfo,
                                DateTimeStyles.None,
                                out L_dtTmpDateTime))
            {
                return false;
            }
            else
            {
                p_dtDateTime = L_dtTmpDateTime;
                return true;
            }
        }


        /// <summary>
        /// Converts a DB string value to a boolean one
        /// </summary>
        /// <param name="p_sValue">The value.</param>
        /// <returns>True if operation succeeds, otherwise false</returns>
        public static bool ConvertToBoolean(string p_sValue)
        {
            if (string.IsNullOrEmpty(p_sValue))
                return false;
            return (p_sValue.Equals("1") || p_sValue.Equals(bool.TrueString));
        }

        /// <summary>
        /// Converts a boolean value to a string one.
        /// </summary>
        /// <param name="p_bValue">if set to <c>true</c> [value].</param>
        /// <returns></returns>
        public static string ConvertFromBoolean(bool p_bValue)
        {
            if (p_bValue)
                return "1";
            return "0";
        }

        /// <summary>
        /// Parses the mask.
        /// </summary>
        /// <param name="p_sP">The p.</param>
        /// <returns></returns>
        public static string ParseMask(string p_sP)
        {
            if (string.IsNullOrEmpty(p_sP))
                return string.Empty;
            StringBuilder parsedMask = new StringBuilder();
            foreach (char c in p_sP)
            {
                switch (c)
                {
                    case '0':
                        parsedMask.Append('n');
                        break;
                    default:
                        parsedMask.Append(c);
                        break;
                }
            }
            return parsedMask.ToString();
        }

        /// <summary>
        /// Strings the upper first only.
        /// </summary>
        /// <param name="p_sStr">The s.</param>
        /// <returns></returns>
        public static string StringUpperFirstOnly(string p_sStr)
        {
            if (!string.IsNullOrEmpty(p_sStr))
            {
                string upper = p_sStr.Substring(0, 1).ToUpperInvariant();
                StringBuilder sb = new StringBuilder(upper);
                for (int i = 1; i < p_sStr.Length; i++)
                {
                    string sTmp = p_sStr[i].ToString();
                    if (IsUppercase(sTmp) && p_sStr[i - 1] != ' ')
                        sb.Append(sTmp.ToUpperInvariant());
                    else
                        sb.Append(sTmp.ToLowerInvariant());
                }

                return sb.ToString();
                //string upper = s.Substring(0, 1).ToUpper();
                //string lower = s.Substring(1).ToLower();
                //return string.Concat(upper, lower);
            }
            return p_sStr;
        }

        /// <summary>
        /// Determines whether the specified STR is uppercase.
        /// </summary>
        /// <param name="p_sStr">The STR.</param>
        /// <returns>
        /// 	<c>true</c> if the specified STR is uppercase; otherwise, <c>false</c>.
        /// </returns>
        private static bool IsUppercase(string p_sStr)
        {
            //variable to hold our return value
            bool upper = false;
            //variable to hold our search pattern
            string pattern = "[a-zçàâäéèëêêîïôöùûüÿ]"; //"\\p{L}";
            try
            {
                Regex AllCaps = new Regex(pattern);
                if (AllCaps.IsMatch(p_sStr))
                {
                    upper = false;
                }
                else
                {
                    upper = true;
                }
            }
            catch
            {
                upper = false;
            }
            return upper;
        }

      
        /// <summary>
        /// Check if lists are equals (elements inside are equals)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_oList1">The list1.</param>
        /// <param name="p_oList2">The list2.</param>
        /// <returns></returns>
        public static bool Equals<T>(List<T> p_oList1, List<T> p_oList2)
        {
            if (p_oList1 == null && p_oList2 == null)
                return true;
            if ((p_oList1 == null && p_oList2 != null) || (p_oList1 != null && p_oList2 == null))
                return false;
            if (p_oList1.Count != p_oList2.Count)
                return false;
            for (int i = 0; i < p_oList1.Count; i++)
            {
                if (!p_oList1[i].Equals(p_oList2[i]))
                    return false;
            }
            return true;
        }


        /// <summary>
        /// Gets the last changed date.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_oObjectList">The object list.</param>
        /// <param name="p_sPropertyName">Name of the property.</param>
        /// <returns></returns>
        public static DateTime GetLastChangedDate<T>(List<T> p_oObjectList, string p_sPropertyName)
        {
            DateTime lastDate = DateTime.MinValue;
            foreach (T obj in p_oObjectList)
            {
                object lastChangedDateObject = typeof(T).GetProperty(p_sPropertyName).GetValue(obj, null);
                DateTime lastChangedDate = DateTime.Parse(lastChangedDateObject.ToString());
                if (DateTime.Compare(lastChangedDate, lastDate) > 0)
                    lastDate = lastChangedDate;
            }
            return lastDate;
        }

        /// <summary>
        /// Gets the name of the column.
        /// </summary>
        /// <param name="p_oColumn">The column.</param>
        /// <returns></returns>
        public static string GetColumnName(DataColumn p_oColumn)
        {
            return p_oColumn.ColumnName;
        }

        /// <summary>
        /// Merges the lists.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_oList1">The list1.</param>
        /// <param name="p_oList2">The list2.</param>
        /// <returns></returns>
        public static List<T> MergeLists<T>(List<T> p_oList1, List<T> p_oList2)
        {
            foreach (T obj in p_oList2)
            {
                if (p_oList1.Contains(obj))
                {
                    int position = p_oList1.IndexOf(obj);
                    p_oList1.RemoveAt(position);
                    p_oList1.Insert(position, obj);
                }
                else
                {
                    p_oList1.Add(obj);
                }
            }
            return p_oList1;
        }

        /// <summary>
        /// Merges the lists.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_oList1">The list1.</param>
        /// <param name="p_oList2">The list2.</param>
        /// <param name="p_sPropertyName">Name of the property.</param>
        /// <returns></returns>
        public static List<T> MergeLists<T>(List<T> p_oList1, List<T> p_oList2, string p_sPropertyName)
        {
            foreach (T obj in p_oList2)
            {
                bool inserted = false;
                PropertyInfo pi2 = obj.GetType().GetProperty(p_sPropertyName);
                object pi2Value = pi2.GetValue(obj, null);
                int size = p_oList1.Count;
                for (int i = size - 1; i >= 0; i--)
                {
                    T objList1 = p_oList1[i];
                    PropertyInfo pi1 = objList1.GetType().GetProperty(p_sPropertyName);
                    object pi1Value = pi1.GetValue(objList1, null);
                    if (pi2Value.Equals(pi1Value))
                    {
                        p_oList1.RemoveAt(i);
                        p_oList1.Insert(i, obj);
                        inserted = true;
                        break;
                    }
                }
                if (!inserted)
                {
                    p_oList1.Add(obj);
                }
                //if (list1.Contains(obj))
                //{
                //    int position = list1.IndexOf(obj);
                //    list1.RemoveAt(position);
                //    list1.Insert(position, obj);
                //}
                //else
                //{
                //    list1.Add(obj);
                //}
            }
            return p_oList1;
        }

        /// <summary>
        /// Get the position of the specified element in the given list (the object must have its Equals
        /// operation overriden
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_oCollectionElements">The collection elements.</param>
        /// <param name="p_oObjectToFind">The object to find.</param>
        /// <returns>The position of the object if successful; otherwise -1</returns>
        public static int IndexOf<T>(IList p_oCollectionElements, T p_oObjectToFind)
        {
            for (int i = 0; i < p_oCollectionElements.Count; i++)
            {
                object obj = p_oCollectionElements[i];
                //Check if list object has a DataValue property (come from Infragistics)
                PropertyInfo pi = obj.GetType().GetProperty("DataValue");
                if (pi != null)
                {
                    obj = pi.GetValue(obj, null);
                }
                else
                {
                    pi = obj.GetType().GetProperty("ListObject");
                    if (pi != null)
                    {
                        obj = pi.GetValue(obj, null);
                    }
                    else
                    {
                        pi = obj.GetType().GetProperty("Value");
                        if (pi != null)
                        {
                            obj = pi.GetValue(obj, null);
                        }
                    }
                }

                if (obj.Equals(p_oObjectToFind))
                {
                    return i;
                }

            }
            return -1;
        }

        /// <summary>
        /// Determines whether a help file exist for the current iso language
        /// </summary>
        /// <param name="p_sHelpFileNameUrl">The help file name URL.</param>
        /// <returns>
        /// 	<c>true</c> if [is help file exist]; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsHelpFileExist(string p_sHelpFileNameUrl)
        {
            return File.Exists(p_sHelpFileNameUrl);
        }

        /// <summary>
        /// Compares the versions.
        /// </summary>
        /// <param name="p_oVersion1">The version1.</param>
        /// <param name="p_oVersion2">The version2.</param>
        /// <returns></returns>
        public static int CompareVersions(Version p_oVersion1, Version p_oVersion2)
        {
            if (p_oVersion1 == null && p_oVersion2 == null)
                return 0;
            if (p_oVersion1 == null)
                return 1;
            return p_oVersion1.CompareTo(p_oVersion2);
        }
    }
}
